libc - aligned_alloc
void* aligned_alloc(size_t alignment, size_t size);
Alignment Parameter:
Must be a power of two:
alignment == 2^n
(2, 4, 8, 16, ..., 4096, etc.)Minimum value: At least
sizeof(void*)
(8 bytes on 64-bit systems)No upper limit: But practically limited by system architecture
Size Parameter:
Must be multiple of alignment:
size % alignment == 0
Non-zero: Must request >0 bytes
Return Value:
Success: Returns pointer to allocated memory
Failure: Returns
NULL
and setserrno
to:EINVAL
: Invalid parametersENOMEM
: Insufficient memory
Code example:
use std::{ptr::NonNull, slice};
fn aligned_alloc(alignment: usize, size: usize) -> Result, &'static str> {
if alignment == 0 || (alignment & (alignment - 1)) != 0 {
return Err("Alignment must be a power of two");
}
if alignment < size_of::() {
return Err("Alignment must be at least platform pointer size");
}
if size == 0 || size % alignment != 0 {
return Err("Size must be multiple of alignment");
}
let ptr = unsafe { libc::aligned_alloc(alignment, size) as *mut u8 };
if ptr.is_null() {
return Err("Memory allocation failed");
}
if (ptr as usize) % alignment != 0 {
unsafe { libc::free(ptr as *mut libc::c_void) };
return Err("Returned pointer is not properly aligned");
}
Ok(unsafe { NonNull::new_unchecked(ptr) })
}
fn main() {
let page_size = unsafe { libc::sysconf(libc::_SC_PAGESIZE) } as usize;
let size = 2 * page_size;
let ptr = match aligned_alloc(page_size, size) {
Ok(p) => p,
Err(e) => panic!("Allocation err: {e:?}"),
};
let slice = unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), size) };
slice.fill(1);
println!("slice: {}", slice.len());
unsafe { libc::free(ptr.as_ptr() as *mut libc::c_void) };
}
Special attention must be paid to the fact that aligned_alloc(alignment, size)
strictly requires size to be an integer multiple of alignment. Violating this rule will result in undefined behavior (UB).